#pragma once
// QtVideoStreamParser.hpp — 视频专用解析器（video-only）
// 只解析/解码 type==106 的视频流消息；控制面(type=101..105)已在上层分拣处理。
// 协议帧格式： [4B 小端 JSON长度][JSON UTF-8][可选 extradata][可选 data]
// - 视频流：4B+JSON 后紧跟 extradata 与 data（二进制长度在 JSON: extradata_size/data_size）
// 依赖：QtCore/Gui、nlohmannjson.hpp、VideoDecoder.hpp（输出 BGRA 与 QImage::Format_ARGB32 匹配）

#include <QObject>
#include <QByteArray>
#include <QImage>
#include <QMetaType>

#include <memory>
#include <string>
#include <cstring>

#include "../nlohmannjson.hpp"
#include "VideoDecoder.hpp" // 解码到 BGRA（与 Qt ARGB32/RGB32 内存布局兼容）

namespace xclient {

// 仅保留视频类型常量（可直接使用 106，这里声明便于阅读）
static constexpr int REQUEST_VIDEOSTREAM = 106;

// ---- 小端读取工具 ----
static inline uint32_t load_le32(const char* p) {
    uint32_t v; std::memcpy(&v, p, sizeof(v));
#if defined(__BYTE_ORDER__) && (__BYTE_ORDER__ != __ORDER_LITTLE_ENDIAN__)
    v = __builtin_bswap32(v);
#endif
    return v;
}

// =====================================================================================
// VideoStreamParser（视频-only）
// 【流程总览】：feed(网络字节) → processBuffer()
//   1) 取 4B JSON 长度 → 2) 解析 JSON(type/尺寸/time_base/offsets) → 3) 仅接受 type==106
//   4) 收齐 extradata/data → 5) 按需重建 VideoDecoder → 6) 关键帧同步
//   7) 组装 AVPacket → 8) 调 DecodeAllAvailableFrames → 9) BGRA→QImage → 10) emit frameReady
//   11) 丢弃已消费字节 → 下一条消息
// =====================================================================================
class VideoStreamParser : public QObject {
    Q_OBJECT
public:
    explicit VideoStreamParser(QObject* parent=nullptr) : QObject(parent) {
        qRegisterMetaType<QImage>("QImage"); // 允许跨线程信号传 QImage
    }

    // 输入：把网络收到的原始字节“喂”进来（可多次，支持半包/粘包）
    void feed(const char* data, int len) {
        if (len <= 0) return;
        buffer_.append(data, len);
        processBuffer();
    }
    void feed(const QByteArray& chunk) {
        if (chunk.isEmpty()) return;
        buffer_.append(chunk);
        processBuffer();
    }

    // 断线/重连/切流时清空状态
    void reset() {
        buffer_.clear();
        decoder_.reset();                 // 析构会 Flush 并打印统计
        last_codec_ = AV_CODEC_ID_NONE;
        last_w_ = last_h_ = 0;
        last_extradata_.clear();
        synced_ = false;                  // 重新等待关键帧
    }

signals:
    // 解码后的图像帧（ARGB32），timestamp：秒（未知为 -1）
    void frameReady(const QImage& img, double timestamp);
    // 解析/解码错误
    void errorOccurred(const QString& msg);

private:
    // 解析主循环：尽可能消费 buffer_ 里的完整“视频帧消息”
    void processBuffer() {
        while (true) {
            // (1) 是否至少有 4 字节（JSON 长度头）
            if (buffer_.size() < 4) return;

            const uint32_t json_len = load_le32(buffer_.constData());
            const int need_json_total = 4 + static_cast<int>(json_len);

            // 基本守门（防异常包/攻击）
            if (json_len == 0 || json_len > (100 * 1024)) { // JSON 上限 100KB
                emit errorOccurred("非法 JSON 长度");
                buffer_.clear();
                return;
            }
            if (buffer_.size() < need_json_total) return; // 半包：等待更多字节

            // (2) 解析 JSON（只读，不动二进制尾部）
            const char* base = buffer_.constData();
            const char* json_ptr = base + 4;
            std::string json_str(json_ptr, json_ptr + json_len);

            nlohmann::json j;
            try { j = nlohmann::json::parse(json_str); }
            catch (const std::exception& e) {
                // JSON 坏包：丢弃 4B+JSON，继续向后解析
                emit errorOccurred(QString("JSON 解析失败: %1").arg(e.what()));
                buffer_.remove(0, need_json_total);
                continue;
            }

            // (3) 仅接受视频类型 106；若出现其他类型（理论上不应出现），记录并丢弃
            const int type = j.value("type", 0);
            if (type != REQUEST_VIDEOSTREAM) {
                emit errorOccurred(QString("非视频流类型: %1（该解析器为 video-only）").arg(type));
                buffer_.remove(0, need_json_total);
                continue;
            }

            // (4) 检查二进制尾部是否收齐（extradata + data）
            const int extra_sz = j.value("extradata_size", 0);
            const int data_sz  = j.value("data_size", 0);
            const int total_need = need_json_total + extra_sz + data_sz;
            if (buffer_.size() < total_need) return; // 半包：等待更多

            // 取出二进制区段
            int off = need_json_total;
            QByteArray extradata; if (extra_sz > 0) { extradata = buffer_.mid(off, extra_sz); off += extra_sz; }
            QByteArray data;      if (data_sz  > 0) { data      = buffer_.mid(off, data_sz ); off += data_sz;  }

            // (5) 组装 decoder 配置，并在参数变化时重建解码器
            VideoDecoder::DecoderConfig cfg;
            cfg.codec_id  = static_cast<AVCodecID>( j.value("codec_id", (int)AV_CODEC_ID_NONE) );
            cfg.width     = j.value("width",  0);
            cfg.height    = j.value("height", 0);
            const int tnum = j["time_base"].value("num", 1);
            const int tden = j["time_base"].value("den", 1);
            cfg.time_base = AVRational{ tnum, tden };
            if (extra_sz > 0) {
                cfg.extradata.assign(reinterpret_cast<const uint8_t*>(extradata.constData()),
                                     reinterpret_cast<const uint8_t*>(extradata.constData()) + extradata.size());
            }

            const bool extradata_changed = (!extradata.isEmpty() && extradata != last_extradata_);
            const bool need_recreate =
                (!decoder_) || (!decoder_->IsValid()) ||
                extradata_changed ||
                cfg.width  != last_w_  || cfg.height != last_h_ ||
                cfg.codec_id != last_codec_;

            if (need_recreate) {
                decoder_ = std::make_unique<VideoDecoder>(cfg); // —— 使用 VideoDecoder：构造/重建
                last_w_ = cfg.width;
                last_h_ = cfg.height;
                last_codec_ = cfg.codec_id;
                if (extradata_changed) last_extradata_ = extradata;

                // 重建后等待关键帧（IDR）再入画，避免花屏
                synced_ = false;

                if (!decoder_ || !decoder_->IsValid()) {
                    emit errorOccurred("解码器初始化失败");
                    buffer_.remove(0, total_need); // 丢弃本条消息
                    continue;
                }
            }

            // (6) 关键帧同步：仅从关键帧开始进行解码/显示
            const bool is_key = j.value("key", false);
            if (!synced_) {
                if (!is_key) { buffer_.remove(0, total_need); continue; } // 未同步且不是关键帧：丢弃
                synced_ = true; // 收到关键帧，开始解码显示
            }

            // (7) 封装 AVPacket（把 data 写入 pkt->data，附带 pts/dts/key）
            AVPacket* pkt = av_packet_alloc();
            if (!pkt) {
                emit errorOccurred("av_packet_alloc 失败");
                buffer_.remove(0, total_need);
                continue;
            }
            if (av_new_packet(pkt, data.size()) < 0) {
                emit errorOccurred("av_new_packet 失败");
                av_packet_free(&pkt);
                buffer_.remove(0, total_need);
                continue;
            }
            std::memcpy(pkt->data, data.constData(), data.size());
            pkt->size = data.size();
            pkt->pts  = j.value("pts",  (int64_t)AV_NOPTS_VALUE);
            pkt->dts  = j.value("dts",  (int64_t)AV_NOPTS_VALUE);
            if (is_key) pkt->flags |= AV_PKT_FLAG_KEY;

            // (8) 解码：send(pkt) →（内部若 EAGAIN 会先 receive 再重试）→ receive 0~N 帧 → sws 到 BGRA
            auto frames = decoder_->DecodeAllAvailableFrames(pkt);
            av_packet_free(&pkt); // 解码器已消费 pkt，立即释放

            // (9) BGRA → QImage（零拷贝包裹 shared_ptr），发射帧信号
            for (auto& f : frames) {
                if (!f || !f->data || f->width<=0 || f->height<=0) continue;

                // 用自定义清理器把 shared_ptr 生命周期托给 QImage，避免悬垂
                auto* keeper = new std::shared_ptr<uint8_t>(f->data);
                QImage img( f->data.get(), f->width, f->height, f->stride,
                           QImage::Format_ARGB32,
                           [](void* info){ auto* p = static_cast<std::shared_ptr<uint8_t>*>(info); delete p; },
                           keeper );

                emit frameReady(img, f->timestamp >= 0 ? f->timestamp : -1.0);
            }

            // (10) 丢弃已消费字节（4B + JSON + extradata + data），继续下一条
            buffer_.remove(0, total_need);
        }
    }

private:
    QByteArray buffer_;                     // 粘包缓冲（承接半包/多包）
    std::unique_ptr<VideoDecoder> decoder_; // 解码器实例（输出 BGRA）

    // 上一次参数快照：用于判断是否需要重建解码器
    AVCodecID last_codec_ = AV_CODEC_ID_NONE;
    int last_w_ = 0, last_h_ = 0;
    QByteArray last_extradata_;

    bool synced_ = false;                   // 是否已与关键帧同步（收到 IDR 后置 true）
};

} // namespace xclient
